package com.qaml.mes.device.domain.service;

import cn.hutool.core.collection.CollectionUtil;
import com.earth.except.error.BusinessException;
import com.earth.user.AuthSsoContext;
import com.earth.user.SsoLoginUser;
import com.qaml.mes.device.api.HolidayApplyService;
import com.qaml.mes.device.dao.CheckUpkeepRecordDO;
import com.qaml.mes.device.dao.CheckUpkeepUserDO;
import com.qaml.mes.device.dao.HolidayApplyDO;
import com.qaml.mes.device.repository.CheckUpkeepRecordRepository;
import com.qaml.mes.device.repository.CheckUpkeepUserRepository;
import com.qaml.mes.device.repository.HolidayApplyRepository;
import com.qaml.mes.device.utils.DateUtils;
import com.qaml.mes.device.domain.convert.HolidayApplyConvert;
import com.qaml.mes.device.dto.eqp.HolidayApplyDTO;
import com.qaml.mes.device.dto.eqp.HolidayApplyOrderIdDTO;
import com.qaml.mes.device.enums.*;
import com.qaml.mes.device.vo.eqp.HolidayApplyAuthVO;
import com.qaml.mes.device.vo.eqp.HolidayApplyVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 假日申请表 服务实现类
 * </p>
 *
 * @author leikai
 * @since 2024-03-04
 */
@Service
public class HolidayApplyServiceImpl implements HolidayApplyService {

    @Resource
    private HolidayApplyRepository holidayApplyRepository;

    @Resource
    private CheckUpkeepUserRepository checkUpkeepUserRepository;

    @Resource
    private CheckUpkeepRecordRepository checkUpkeepRecordRepository;

    /**
     * 创建休假申请
     *
     * @param holidayApplyDTO 假期申请
     */
    @Override
    public void createHolidayApply(HolidayApplyDTO holidayApplyDTO) {

        SsoLoginUser ssoLoginUser = AuthSsoContext.getSsoLoginUser();
        List<CheckUpkeepUserDO> checkUpkeepUserDOList = checkUpkeepUserRepository.getRecheckUserList(CheckUpkeepUserTypeEnum.CHECK.getType());
        if (!CollectionUtils.isEmpty(checkUpkeepUserDOList)) {
            List<String> userIds = checkUpkeepUserDOList.stream().map(CheckUpkeepUserDO::getUserId).collect(Collectors.toList());
            // 是否点检人
            if (!userIds.contains(ssoLoginUser.getUserId())) {
                throw new BusinessException(500, "您没有权限操作该申请");
            }
        }

        // 1,将假期申请DTO转换为DO
        HolidayApplyDO holidayApplyDO = HolidayApplyConvert.INSTANCE.do2DTO(holidayApplyDTO);
        // 2,判断是否有对应的申请已经存在  -->根据类型和时间范围
        //  2.2 如果不存在   --根据类型+时间节点作为唯一标识

        // a,从系统获取检保(申请)人信息(当前登录用户) -- 全局获取
        holidayApplyDO.setUserId(ssoLoginUser.getUserId());
        holidayApplyDO.setUserName(ssoLoginUser.getUserName());

        // b,前端传入审核人信息(根据id获取)   dto中包含
        holidayApplyDO.setRecheckUserId(holidayApplyDTO.getRecheckUserId());
        holidayApplyDO.setRecheckUserName(holidayApplyDTO.getRecheckUserName());

        // new Date()  当前时间
        Date now = new Date();

        // 判断有无传入检保日期
        // d.1 如果没有传入检保日期

        if (holidayApplyDTO.getCheckUpkeepDate() == null) {
            setStartAndEndTime(holidayApplyDO, now, holidayApplyDTO.getType());
            // d.2 如果传入了检保日期
        } else {
            setStartAndEndTime(holidayApplyDO, holidayApplyDTO.getCheckUpkeepDate(), holidayApplyDTO.getType());
        }
        // 设置创建用户
        holidayApplyDO.setCreateUserName(ssoLoginUser.getUserName());
        // e,状态(有默认值为待审核)
        holidayApplyDO.setStatus(HolidayApplyEnum.UNDER_REVIEW.getType());
        // f,提交时间(当前时间)
        holidayApplyDO.setCommitTime(now);
        // g,审核时间(默认为空)
        try {
            holidayApplyRepository.createHolidayApply(holidayApplyDO);
        } catch (Exception e) {
            //  2.1如果已经存在  --根据类型+时间节点作为唯一标识
            throw new BusinessException(BizErrorEnums.HOLIDAY_APPLY_ERROR);
        }
    }

    /**
     * 传入开始，结束时间  -- 根据类型
     * <p>
     * c,类型的传入（类型分开）
     * 点检 or 保养
     *
     * @param holidayApplyDO
     * @param date
     * @param type
     */
    public void setStartAndEndTime(HolidayApplyDO holidayApplyDO, Date date, String type) {
        if (CheckUpkeepMessageTypeEnum.CHECK.getType().equals(type)) {
            holidayApplyDO.setStartTime(DateUtils.getStartDate(date));
            holidayApplyDO.setEndTime(DateUtils.getEndDate(date));
            return;
        }
        if (CheckUpkeepMessageTypeEnum.UPKEEP.getType().equals(type)) {
            holidayApplyDO.setStartTime(DateUtils.getStartDateByWeek(date));
            holidayApplyDO.setEndTime(DateUtils.getEndDateByWeek(date));
            return;
        }
        throw new BusinessException(BizErrorEnums.UNKNOWN_TYPE);
    }

    /**
     * 获取休假申请详情
     *
     * @param holidayApplyDTO 假期申请
     * @return 假期申请详情
     */
    @Override
    public HolidayApplyAuthVO getHolidayApply(HolidayApplyDTO holidayApplyDTO) {
        HolidayApplyAuthVO holidayApplyAuthVO = new HolidayApplyAuthVO();
        HolidayApplyDO holidayApplyDO = holidayApplyRepository.getHolidayApply(holidayApplyDTO);
        String currentUserId = AuthSsoContext.getCurrentUserId();
        List<CheckUpkeepUserDO> checkUpkeepUserDOList = checkUpkeepUserRepository.getRecheckUserList(CheckUpkeepUserTypeEnum.CHECK.getType());
        if (!CollectionUtils.isEmpty(checkUpkeepUserDOList)) {
            List<String> userIds = checkUpkeepUserDOList.stream().map(CheckUpkeepUserDO::getUserId).collect(Collectors.toList());
            // 是否点检人
            if (userIds.contains(currentUserId)) {
                holidayApplyAuthVO.setCanCheck(Boolean.TRUE);
            }
        }
        if (holidayApplyDO != null) {
            // 是否存在假期申请
            holidayApplyAuthVO.setHasApply(Boolean.TRUE);
            // 状态  待审核  已通过
            holidayApplyAuthVO.setStatus(holidayApplyDO.getStatus());
            HolidayApplyVO holidayApplyVO = HolidayApplyConvert.INSTANCE.do2VO(holidayApplyDO);
            if (holidayApplyVO.getRecheckUserId().equals(currentUserId)) {
                // 是否复核人
                holidayApplyVO.setCanRecheck(Boolean.TRUE);
                holidayApplyAuthVO.setCanRecheck(Boolean.TRUE);
            }
            holidayApplyAuthVO.setHolidayApplyVO(holidayApplyVO);
        }
        return holidayApplyAuthVO;
    }

    /**
     * 判断当前登录用户是否有权限   --- 只用于前端按钮的显示
     *
     * @param holidayApplyVO
     */
    private void hasAuditAuth(HolidayApplyVO holidayApplyVO) {
        SsoLoginUser ssoLoginUser = AuthSsoContext.getSsoLoginUser();
        if (holidayApplyVO.getRecheckUserId().equals(ssoLoginUser.getUserId())) {
            holidayApplyVO.setCanRecheck(Boolean.TRUE);
        }
    }

    /**
     * 判断当前用户是否可以执行操作
     */
    private void checkAuth(String recheckUserId) {
        if (recheckUserId.isEmpty()) {
            throw new IllegalArgumentException("审核人员Id不能为空");
        }
        SsoLoginUser ssoLoginUser = AuthSsoContext.getSsoLoginUser();
        if (!recheckUserId.equals(ssoLoginUser.getUserId())) {
            throw new BusinessException(500, "您没有权限操作该申请");
        }
    }

    /**
     * 通过假期申请
     *
     * @param holidayApplyOrderId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void passCommit(HolidayApplyOrderIdDTO holidayApplyOrderId) {
        // 1,获取假期申请表
        HolidayApplyDO holidayApplyDO = holidayApplyRepository.getById(holidayApplyOrderId.getHolidayApplyId());
        if (Objects.isNull(holidayApplyDO)) {
            throw new BusinessException(BizErrorEnums.NOT_ALREADY_EXISTS_ID);
        }
        // 获取当天的检保任务
        List<CheckUpkeepRecordDO> checkUpkeepRecordDOList = checkUpkeepRecordRepository.getByTypeAndCheckUpkeepDate(CheckUpkeepTypeEnum.CHECK.getType(), holidayApplyDO.getStartTime());
        if (!CollectionUtil.isEmpty(checkUpkeepRecordDOList)) {
            List<String> ids = checkUpkeepRecordDOList.stream().map(CheckUpkeepRecordDO::getId).collect(Collectors.toList());
            // 给检保任务打上标记
            checkUpkeepRecordRepository.updateHolidayTipByIds(ids);
        }
        // 判断当前用户是否有权限操作
        checkAuth(holidayApplyDO.getRecheckUserId());
        // 2,设置假期申请单状态为 已通过
        holidayApplyDO.setStatus(HolidayApplyEnum.PASSED.getType());
        // 3,获取new Date() 作为审核时间recheck_time 传入
        holidayApplyDO.setRecheckTime(new Date());
        // 4,更新休假申请表
        holidayApplyRepository.updateById(holidayApplyDO);
    }

    /**
     * 驳回假期申请
     *
     * @param holidayApplyOrderId
     */
    @Override
    public void overruledCommit(HolidayApplyOrderIdDTO holidayApplyOrderId) {
        // 1,获取假期申请表
        HolidayApplyDO holidayApplyDO = holidayApplyRepository.getById(holidayApplyOrderId.getHolidayApplyId());
        if (Objects.isNull(holidayApplyDO)) {
            throw new BusinessException(BizErrorEnums.NOT_ALREADY_EXISTS_ID);
        }
        // 判断当前用户是否有权限进行操作
        checkAuth(holidayApplyDO.getRecheckUserId());

        // 2,设置假期申请单状态为 未通过
        holidayApplyDO.setStatus(HolidayApplyEnum.REJECTED.getType());
        // 3,获取new Date() 作为审核时间recheck_time 传入
        holidayApplyDO.setRecheckTime(new Date());
        // 4,逻辑删除掉申请单
        holidayApplyDO.setIsDeleted(1);
        // 5,更新休假申请表
        holidayApplyRepository.updateById(holidayApplyDO);
    }


}


